#ifndef STACK_H
#define STACK_H

#include "array.h"


/**
	Pseudotemplata wykorzystujaca preprocesor.
	
	Na przyklad, Stack(int) wraz z DefStack(T) tworza
	
	intStack oraz
	- intStack_new
	- intStack_delete
	- intStack_push
	- intStack_pop
	- intStack_top
	- intStack_empty
*/
#define Stack(T)  \
T##Stack T##Stack_new() {  \
   T##Stack res;  \
   res.array = T##Array_new();   \
   return res; \
}  \
void T##Stack_delete(T##Stack* st) {   \
   assert (st != null); \
   T##Array_delete(&st->array);  \
}  \
void T##Stack_push(T##Stack* st, T x) {   \
   assert (st != null); \
   T##Array_append(&st->array, x);  \
}  \
void T##Stack_pop(T##Stack* st) {   \
   assert (st != null); \
   assert (st->array.length > 0);   \
   --st->array.length;  \
}  \
T T##Stack_top(T##Stack* st) {   \
   assert (st != null); \
   assert (st->array.length > 0);   \
   return st->array.data[st->array.length-1];   \
}  \
bool T##Stack_empty(T##Stack* st) { \
   assert (st != null); \
   return 0 == st->array.length; \
}



#define DefStack(T)  \
typedef struct {  \
   T##Array array;   \
} T##Stack; \
T##Stack T##Stack_new();  \
void T##Stack_delete(T##Stack* st);	\
void T##Stack_push(T##Stack* st, T x);  \
void T##Stack_pop(T##Stack* st);  \
T T##Stack_top(T##Stack* st);  \
bool T##Stack_empty(T##Stack* st);


#endif	// STACK_H
